//「一本通 3.1 练习 4」Tree
//二分，用kruskal算法不断求最小生成树，每次将白色边给定增量x,通过调整x,可使白色边到达要求的need条
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXV=50000;
const int MAXE=100000;
int v,e,need;
struct Edge
{
    int u,v,w,col;
    bool operator<(const Edge other)const{
        return w==other.w?col<other.col:w<other.w;
    }
};
Edge edges[MAXE];
struct UFS{
    int fa[MAXV+1];
    void init(){
        for(int i=0;i<v;i++) fa[i]=i;//此题点从0开始
    }
    int find_set(int x){
        if (fa[x]!=x) fa[x]=find_set(fa[x]);
        return fa[x];
    }
    void union_set(int x,int y){
        int hx=find_set(x);
        int hy=find_set(y);
        fa[hy]=hx;
    }
};
UFS ufs;
int min_sumc,cnt,cnt_white;

void kruskal(int x){
    for(int i=0;i<e;i++)
        if (!edges[i].col) edges[i].w+=x;
    sort(edges,edges+e);
    ufs.init();
    min_sumc=0;
    cnt=0,cnt_white=0;
    for(int i=0;i<e;i++){
        int ru=ufs.find_set(edges[i].u);
        int rv=ufs.find_set(edges[i].v);
        if (ru!=rv){
            min_sumc+=edges[i].w;
            cnt++;
            if (!edges[i].col) cnt_white++;
            ufs.union_set(ru,rv);
        }
        if (cnt==v-1) break;
    }
    for(int i=0;i<e;i++)
        if (!edges[i].col) edges[i].w-=x;
}
int ans;
int main(){
    cin>>v>>e>>need;
    for(int i=0;i<e;i++){
        int s,t,c,col;
        cin>>s>>t>>c>>col;
        edges[i]={s,t,c,col};
    }
    
    int left=-100,right=100;
    while (left<=right){
        int mid=(left+right)/2;
        kruskal(mid);
        if (cnt_white>=need){
            ans=min_sumc-need*mid;//此处用need*mid而不是cnt_white*mid为什么？
            left=mid+1;
        }else {
            right=mid-1;
        }
    }
    cout<<ans;
}
